#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <stdio.h>

#include "librtmp/rtmp_sys.h"
#include "librtmp/log.h"
#include  "flv_parse.h"
#include  "aac.h"
#include  "adts.h"
#include  "srs_librtmp.h"
#include  "h264.h"
 uint8_t sps_len = 0;
    uint8_t pps_len = 0;
    uint8_t *sps_buffer = nullptr;
    uint8_t *pps_buffer = nullptr;
    uint8_t *nal_unit_buffer = nullptr;

    uint8_t mAudioProfile, mSampleRate, mChannels;
    bool is_key_frame;
int main(int argc, char* argv[])
{
                 FILE * mFp = fopen("h264.nal", "awb");
        FLV_Parser flv;	
	int nRead;
	bool bLiveStream=true;				
	
	int bufsize=1024*1024*10;			
	char *buf=(char*)malloc(bufsize);
	
	FILE *fp=fopen("receive.flv","wb");
	if (!fp){
		RTMP_LogPrintf("Open File Error.\n");
		return -1;
	}
	
	RTMP_LogSetLevel(RTMP_LOGDEBUG);
 
	RTMP *rtmp=RTMP_Alloc();
	RTMP_Init(rtmp);
	rtmp->Link.timeout=5;	
	if(!RTMP_SetupURL(rtmp,"rtmp://jyjy.tech/live/live"))
	{
		RTMP_Log(RTMP_LOGERROR,"SetupURL Err\n");
		RTMP_Free(rtmp);
		return -1;
	}
	if (bLiveStream){
		rtmp->Link.lFlags|=RTMP_LF_LIVE;
	}
	
	//1hour
	//RTMP_SetBufferMS(rtmp, 3600*1000);		
	
	if(!RTMP_Connect(rtmp,NULL)){
		RTMP_Log(RTMP_LOGERROR,"Connect Err\n");
		RTMP_Free(rtmp);
		return -1;
	}
 
	if(!RTMP_ConnectStream(rtmp,0)){
		RTMP_Log(RTMP_LOGERROR,"ConnectStream Err\n");
		RTMP_Close(rtmp);
		RTMP_Free(rtmp);
		return -1;
	}
 
	while(nRead=RTMP_Read(rtmp,buf,bufsize)){
		fwrite(buf,1,nRead,fp);
                flv.consume(buf, nRead);
		RTMP_Log(RTMP_LOGINFO, "RTMP %d\n",nRead);
                //if(!flv.aq.empty()) {
                if(0) {
		RTMP_LogPrintf("%d\n",flv.aq.size());
                TAG *tag = flv.aq.front();
		RTMP_Log(RTMP_LOGINFO, "Tag typ:%d timestamp %d size %d\n", tag->type, tag->timestamp, tag->data_size);
		RTMP_Log(RTMP_LOGDEBUG, "%x %x %x %x %x %x %x %x %x %x %x\n", tag->tag_data[0], tag->tag_data[1],\
                        tag->tag_data[2],\
                        tag->tag_data[3], tag->tag_data[4],  tag->tag_data[5],  tag->tag_data[6],
                        tag->tag_data[7], tag->tag_data[8],  tag->tag_data[9],  tag->tag_data[10]);
                flv.aq.pop();

             if (tag->type == SRS_RTMP_TYPE_AUDIO) {
            char sound_format = srs_utils_flv_audio_sound_format((char*)tag->tag_data, tag->data_size);
            if (sound_format != SrsAudioCodecIdAAC) {
                 RTMP_Log(RTMP_LOGINFO, "only support AAC\n");
                 break;
            }
            tag->data_size -= AUDIO_TAG_HEADER;
            if (srs_utils_flv_audio_aac_packet_type((char*)tag->tag_data, tag->data_size) == 0 ) {
                 RTMP_Log(RTMP_LOGINFO, "AAC Sequence Header\n");
                 parse_asc((char*)tag->tag_data + AUDIO_TAG_HEADER, tag->data_size, &mAudioProfile, &mSampleRate, &mChannels);
                 printf("size:%d profile:%d  samplerate:%d, channels:%d\n", tag->data_size, mAudioProfile, mSampleRate, mChannels);
            }else {
                 RTMP_Log(RTMP_LOGINFO, "AAC RAW DATA\n");
                 uint8_t adts_header[7];
                 adts_set_sync(adts_header);
                 adts_set_profile(adts_header, mAudioProfile - 1);
                 adts_set_sampling_freq(adts_header, mSampleRate);
                 adts_set_channels(adts_header, mChannels);
                 adts_set_fullness(adts_header, 0x7ff);
                 //normal 1 raw data blocks, FIXME
                 adts_set_num_blocks(adts_header, 0);
                 adts_set_length(adts_header, ADTS_HEADER_SIZE + tag->data_size);
                 uint8_t * buff = new uint8_t[tag->data_size + ADTS_HEADER_SIZE];
                 memcpy(buff, adts_header, ADTS_HEADER_SIZE);
                 memcpy(buff + ADTS_HEADER_SIZE, tag->tag_data+AUDIO_TAG_HEADER, tag->data_size);
                 #if 1
                 printf("%x %x %x %x %x %x %x\n", adts_header[0], adts_header[1] , adts_header[2], adts_header[3], adts_header[4], adts_header[5],adts_header[6]);
                 FILE * fp = fopen("adts.aac", "awb");
                 fwrite(buff, ADTS_HEADER_SIZE + tag->data_size,1, fp);
                 fclose(fp);
                 #endif
            }
        }
                delete tag;


                }

//video

           if(!flv.vq.empty()) {
		RTMP_LogPrintf("%d\n",flv.vq.size());
                TAG *tag = flv.vq.front();
		RTMP_Log(RTMP_LOGINFO, "Tag typ:%d timestamp %d size %d\n", tag->type, tag->timestamp, tag->data_size);
		RTMP_Log(RTMP_LOGDEBUG, "%x %x %x %x %x %x %x %x %x %x %x\n", tag->tag_data[0], tag->tag_data[1],\
                        tag->tag_data[2],\
                        tag->tag_data[3], tag->tag_data[4],  tag->tag_data[5],  tag->tag_data[6],
                        tag->tag_data[7], tag->tag_data[8],  tag->tag_data[9],  tag->tag_data[10]);
                flv.vq.pop();

              if (1){
             char video_codec = srs_utils_flv_video_codec_id((char*)tag->tag_data, tag->data_size);
             if (video_codec != SrsVideoCodecIdAVC) {
                   printf("e\n");
                   break;
             }            
             char *offset;
             is_key_frame = (srs_utils_flv_video_frame_type((char*)tag->tag_data, tag->data_size) == 1);
             char avc_packet_type = srs_utils_flv_video_avc_packet_type((char*)tag->tag_data, tag->data_size);
             if (is_key_frame) {
             }
             if (avc_packet_type == SequenceHeader) {
                 tag->data_size -=  VIDEO_TAG_HEADER;
                 offset = (char*)tag->tag_data + VIDEO_TAG_HEADER;
                 if (tag->data_size < H264AVCC_HEADER) {
                   printf("ee\n");
                    break;
                 }
                 uint8_t nal_unit_len = offset[4] & 0x3;
                 if(nal_unit_len != 3) {
                   printf("eee\n");
                    break;
                 }
                 uint8_t  nb_sps = offset[5] & 0x1f;;
                 if (nb_sps != 1){ 
                   printf("eeee\n");
                    break;
                 }
                 tag->data_size -=  H264AVCC_HEADER;
                 offset += H264AVCC_HEADER;
                 sps_len =  (offset[0] << 8) | offset[1];;
                 sps_buffer = new uint8_t[sps_len + sizeof(nal_start_code)];
                 memcpy(sps_buffer, nal_start_code, sizeof(nal_start_code));
                 memcpy(sps_buffer + sizeof(nal_start_code), offset + 2, sps_len);
                 tag->data_size -= (H264AVCC_SPS_HEADER + sps_len);
                 offset += H264AVCC_SPS_HEADER + sps_len; 
                 uint8_t nb_pps = offset[0] & 0x1f;
                 if (nb_pps != 1){ 
                   printf("eeeee\n");
                    break;
                 }
                 pps_len = (offset[1] << 8) | offset[2];
                 pps_buffer = new uint8_t[pps_len + sizeof(nal_start_code)];
                 memcpy(pps_buffer, nal_start_code, sizeof(nal_start_code));
                 memcpy(pps_buffer + sizeof(nal_start_code), offset + 3 , pps_len);
                 #if 1
                 fwrite(sps_buffer, sps_len + 4, 1, mFp);
                 fwrite(pps_buffer, pps_len + 4, 1, mFp);
                 #endif
                 int datalen = 0;
                 datalen += pps_len + sps_len + 8 ;
             }else {
                 int datalen = 0;
                 if (tag->data_size <= VIDEO_TAG_HEADER)
                     continue;
                 tag->data_size -=  VIDEO_TAG_HEADER;
                 offset = (char*)tag->tag_data + VIDEO_TAG_HEADER;
                 uint8_t *temp = (uint8_t*)offset;
                 uint32_t nal_len = (temp[0] << 24) | (temp[1] << 16) | (temp[2] << 8) | temp[3];
                 datalen += nal_len + sizeof(nal_start_code);
                 nal_unit_buffer = new uint8_t[datalen];
                 memcpy(nal_unit_buffer , nal_start_code, sizeof(nal_start_code));
                 memcpy(nal_unit_buffer + sizeof(nal_start_code), offset + 4, nal_len);

                 #if 1
                 fwrite(nal_unit_buffer, datalen, 1, mFp);
                 printf("==%d\n", datalen);
                 #endif
             }
             }
        delete tag; 
          } //vq




	}
 
	if(fp)
		fclose(fp);
 
	if(buf){
		free(buf);
	}
 
	if (rtmp){
		RTMP_Close(rtmp);
		RTMP_Free(rtmp);
	}	
	return 0;
}
